package com.photoeditor.demo.imageloader;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.common.base.ComponentContext;
import com.photoeditor.R;
import com.photoeditor.demo.util.FLogUtils;
import com.photoeditor.demo.util.ImageManageUtil;

import java.lang.ref.WeakReference;
import java.util.concurrent.CopyOnWriteArrayList;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import me.xiaopan.sketch.Sketch;

import static com.bumptech.glide.request.target.Target.SIZE_ORIGINAL;

public class ImageLoader {
    /**
     * DiskCacheStrategy.NONE： 表示不缓存任何内容
     * DiskCacheStrategy.DATA： 表示只缓存原始图片
     * DiskCacheStrategy.RESOURCE： 表示只缓存转换过后的图片
     * DiskCacheStrategy.ALL ： 表示既缓存原始图片，也缓存转换过后的图片
     * DiskCacheStrategy.AUTOMATIC： 表示让Glide根据图片资源智能地选择使用哪一种缓存策略（默认选项）
     */
    private static RequestOptions options = new RequestOptions()
            .diskCacheStrategy(DiskCacheStrategy.ALL)//表示既缓存原始图片，也缓存转换过后的图片
            .placeholder(R.drawable.ic_default_image);//默认图片



    public static CopyOnWriteArrayList<BitmapLoadListener> mListener = new CopyOnWriteArrayList<>();

    public static final String RESOURCE_PREFIX = "android.resource://";

    public static void loadImage(String url, ImageView imageView) {
        loadImage(url, -1, imageView);
    }

    public static void loadImage(String url, ImageView imageView, int width, int height) {
        loadImage(url, -1, imageView, width, height);
    }

    public static void loadImage(String url, int defaultIcon, ImageView imageView) {
        loadImage(url, defaultIcon, imageView, Priority.LOW);
    }

    public static void loadImage(String url, int defaultIcon, ImageView imageView, int width, int height) {
        loadImage(url, defaultIcon, imageView, Priority.LOW, width, height);
    }

    public static void loadImage(String url, int defaultIcon, ImageView imageView, Priority priority) {
        loadImage(url, defaultIcon, imageView, priority, null, SIZE_ORIGINAL, SIZE_ORIGINAL);
    }

    public static void loadImage(String url, int defaultIcon, ImageView imageView, Priority priority, int width, int height) {
        loadImage(url, defaultIcon, imageView, priority, null, width, height);
    }

    public static void loadImage(String url, int defaultIcon, ImageView imageView, Priority priority,
                                 RequestListener listener, int width, int height) {
        GlideApp.with(ComponentContext.getContext())
                .load(url)
                .override(width, height)
                .priority(priority)
                .placeholder(defaultIcon)
                .listener(listener)
                .into(imageView);
    }

    public static void loadImage(Activity context, String url, int defaultIcon, ImageView imageView) {
        loadImage(context, url, defaultIcon, imageView, null);
    }

    /**
     * @param context
     * @param url
     * @param defaultIcon
     * @param imageView
     * @param listener    注意：listener会被强引用，需要加载网络图片时，不能使用此方法
     */
    public static void loadImage(Activity context, String url, int defaultIcon, ImageView imageView, final OnLoadBitmapListener listener) {
        try {
            GlideApp.with(context)
                    .load(url)
                    .placeholder(defaultIcon)
                    .listener(new RequestListener<Drawable>() {
                        @Override
                        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                            if (listener != null) {
                                listener.onLoadBitmapFinish(null);
                            }
                            return false;
                        }

                        @Override
                        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                            if (listener != null) {
                                listener.onLoadBitmapFinish(resource);
                            }
                            return false;
                        }
                    })
                    .into(imageView);
        } catch (Exception e) {
        }
    }

    /**
     * 加载图片，先显示小图再显示大图
     *
     * @param context
     * @param url
     * @param defaultIcon
     * @param imageView
     * @param listener    注意：listener会被强引用，需要加载网络图片时，不能使用此方法
     */
    public static void loadImageWithThumbnail(Activity context, String url, int degree, int defaultIcon, ImageView imageView, final OnLoadBitmapListener listener) {
        try {
            GlideApp.with(context)
                    .load(url)
                    .fitCenter()
                    .placeholder(defaultIcon)
                    .thumbnail(0.1f)
                    .listener(new RequestListener<Drawable>() {
                        @Override
                        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                            if (listener != null) {
                                listener.onLoadBitmapFinish(null);
                            }
                            return false;
                        }

                        @Override
                        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                            if (listener != null) {
                                listener.onLoadBitmapFinish(resource);
                            }
                            return false;
                        }
                    })
                    .apply(RequestOptions.bitmapTransform(new RotateTransformation(context, degree)))
                    .into(imageView);
        } catch (Exception e) {
        }
    }

    public static void loadImage(Activity context, String url, int defaultIcon, ImageView imageView, boolean fromCache) {
        try {
            GlideApp.with(context)
                    .load(url)
                    .placeholder(defaultIcon)
                    .onlyRetrieveFromCache(true)
                    .into(imageView);
        } catch (Exception e) {
        }
    }

    public static void loadImageOnlyStrongRef(Activity context, String url, final OnLoadBitmapListener listener) {
        try {
            final String finalUrl = url;
            GlideApp.with(context)
                    .asBitmap()
                    .load(url)
                    .into(new SimpleTarget<Bitmap>() {
                        @Override
                        public void onLoadFailed(@Nullable Drawable errorDrawable) {
                            if (listener != null) {
                                listener.onLoadBitmapFinish(null);
                            }
                        }

                        @Override
                        public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
                            if (listener != null) {
                                listener.onLoadBitmapFinish(resource);
                            }
                        }

                    });
        } catch (Exception e) {
        }
    }

    /**
     * 异步加载url，注意listener需要手动remove
     *
     * @param context
     * @param url
     * @param listener 结果回调，注意因内存问题listener只保留弱引用，外部使用时不能使用临时变量
     */
    public static void loadImageOnly(Context context, String url, OnLoadBitmapListener listener) {
        try {
            final String finalUrl = url;
            if (listener != null) {
                mListener.add(new BitmapLoadListener(finalUrl, listener));
            }
            GlideApp.with(context)
                    .asBitmap()
                    .load(finalUrl)
                    .into(new SimpleTarget<Bitmap>() {
                        @Override
                        public void onLoadFailed(@Nullable Drawable errorDrawable) {
                            notifyListener(finalUrl, null);
                        }

                        @Override
                        public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
                            notifyListener(finalUrl, resource);
                        }

                    });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String resourceId2String(Context context, int resourceId) {
        return RESOURCE_PREFIX + context.getPackageName() + "/" + resourceId;
    }

    public static void downloadImageFile(Context context, String url) {
        GlideApp.with(context).downloadOnly().load(url).submit();
    }

    private static class BitmapLoadListener {
        String mUrl;
        WeakReference<OnLoadBitmapListener> mListener;

        public BitmapLoadListener(String url, OnLoadBitmapListener listener) {
            mUrl = url;
            mListener = new WeakReference<OnLoadBitmapListener>(listener);
        }
    }

    private static void notifyListener(String url, Bitmap bitmap) {
        for (BitmapLoadListener listener : mListener) {
            if (listener.mUrl.equals(url) && listener.mListener.get() != null) {
                listener.mListener.get().onLoadBitmapFinish(bitmap);
            }
        }
    }

    public static void removeListener(OnLoadBitmapListener listener) {
        for (BitmapLoadListener tmp : mListener) {
            if (tmp.mListener.get() == listener) {
                mListener.remove(tmp);
                break;
            }
        }
    }

    public interface OnLoadBitmapListener {
        void onLoadBitmapFinish(Object bitmap);
    }

    public static void clearMemoryCache() {
        Sketch.with(ComponentContext.getContext()).getConfiguration().getMemoryCache().clear();
        GlideApp.get(ComponentContext.getContext()).clearMemory();
    }

    public static void onTrimMemroy(int level) {
        Sketch.with(ComponentContext.getContext()).getConfiguration().getMemoryCache().clear();
        GlideApp.get(ComponentContext.getContext()).onTrimMemory(level);
    }

    public static void onLowMemory() {
        clearMemoryCache();
    }

    public static Disposable loadImageFromBase64(final Context context, final String picBase64, final ImageView imageView) {
        return Observable.just(picBase64)
                .map(new Function<String, Bitmap>() {
                    @Override
                    public Bitmap apply(String s) {
                        return ImageManageUtil.base64ToBitmap(picBase64);
                        //return Base64.decode(s, Base64.DEFAULT);
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Bitmap>() {
                    @Override
                    public void accept(Bitmap bitmap) {
                        FLogUtils.i("->>", "accept: glide加载合并后图片");
                        GlideApp.with(context)
                                .load(bitmap)
                                .diskCacheStrategy(DiskCacheStrategy.ALL)
                                .dontAnimate()
                                .centerCrop()
                                .into(imageView);
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) {
                        FLogUtils.e("->>", "accept: " + throwable.toString());
                    }
                });
    }


    public static void loadImage(Context context,String url ,ImageView imageView) {
        Glide.with(context)
                .load(url)
                .apply(options)
                .into(imageView);
    }
    public static void loadImage(Context context,Bitmap bitmap, ImageView imageView) {
        GlideApp.with(context)
                .load(bitmap)
                .onlyRetrieveFromCache(true)
                .into(imageView);
    }
}
